#include "PWM.h"
#include "stm32f10x.h"
#include "stm32f10x_tim.h"
#include "misc.h"
#include "stm32f10x_gpio.h"
#include <math.h>
/**
使用定时器2  tim2
*/
void init_my_pwm_in_tim2(void){
 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; // 控制电机正反转
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB,&GPIO_InitStruct);
    
     // 配置使用内部时钟
    //TIM_InternalClockConfig(TIM2);
    
    // pwm 使用 PA0
 
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; // gpio输出来源于 tim2 ch1 
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStruct);
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
    
    
    
    TIM_InternalClockConfig(TIM2);
    
    TIM_TimeBaseInit(TIM2,&(TIM_TimeBaseInitTypeDef){
        // 最终生成频率为 500Hz 的pwm波
        .TIM_Prescaler=1440-1,
        .TIM_CounterMode = TIM_CounterMode_Up,
        .TIM_Period = 100,
        .TIM_ClockDivision=TIM_CKD_DIV1
    
    });
    
    
    // 配置pwm的占空比为50%
    // 关闭 output compare register preload 模式，写入 oc 寄存器，则立即生效
    TIM_OC3PreloadConfig(TIM2,TIM_OCPreload_Disable);
    
    //TIM_SetCompare1(TIM2,5);
    // 设置输出比较通道3为pwm模式1
    TIM_SelectOCxM(TIM2,TIM_Channel_1,TIM_OCMode_PWM1);
    
    // 配置pwm输出极性
    TIM_OC1PolarityConfig(TIM2,TIM_OCPolarity_High);
    
    // 启用输出比较模式
    TIM_CCxCmd(TIM2,TIM_Channel_1,TIM_CCx_Enable);
    
    //本来还应该配置 TIMx capture/compare mode register 1 (TIMx_CCMR1) 为输出模式 TIM_CCMR1_CC1S = 0
    // 但是输出模式默认就是00，不配置也是可以的
    
    
}
/**
    设置正转（顺时针）
*/
void clockwise_rotate(void){
    GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_RESET);
    GPIO_WriteBit(GPIOB,GPIO_Pin_13,Bit_SET);
}

/**
    设置反转（逆时针）
*/
void counter_clockwise_rotate(void){
    GPIO_WriteBit(GPIOB,GPIO_Pin_13,Bit_RESET);
    GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_SET);
}

void start_pwm(void){
    TIM_Cmd(TIM2,ENABLE);
    clockwise_rotate();
}

void stop_pwm(void){
    GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_RESET);
    GPIO_WriteBit(GPIOB,GPIO_Pin_13,Bit_RESET);
    TIM_Cmd(TIM2,DISABLE);
}

void pwm_init(void){

    // 因为 tim4 是 通用时钟，其连接到了 APB1 上
    // 这里为其使能时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
    //RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    
    // 配置使用内部时钟
    TIM_InternalClockConfig(TIM4);
    
    
    GPIO_Init(GPIOB,&(GPIO_InitTypeDef){
        .GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7,
        .GPIO_Speed=GPIO_Speed_50MHz,
        //Alternate function push-pul 交替功能推挽
        // 把GPIO输出的控制权交给 pwm 输出比较器
        .GPIO_Mode=GPIO_Mode_AF_PP,
    });
    
    // 1.配置预分频器
    // 因为要求对方波的上升沿数量进行计次
    // 所以不需要分频，如果配置了分频，那么就相当于把外部输入的方波进行分频之后
    // 再进行后续处理
    TIM_PrescalerConfig(TIM4,720-1,TIM_PSCReloadMode_Update);
    
    // 2.配置计数器的计数模式
    // 从 0 往上数，直到特定数字
    TIM_CounterModeConfig(TIM4,TIM_CounterMode_Up);
    
    // 3.设置自动重装寄存器的值
    // 输出 pwm 波形
    // 当 CNT 计数器到 自动重装寄存器的值时，
    // 重置 CNT 计数器
    // pwm 波输出的频率 = 72MHz/72/20000 = 50Hz
    TIM_SetAutoreload(TIM4,AUTO_RELOAD_REGISTER_VALUE-1);
    
    
    
    
    // 配置 output compare 1 输出比较寄存器 的影子寄存器（预装值）
    TIM_OC1PreloadConfig(TIM4,TIM_OCPreload_Enable);
    
    // 配置时基单元
    // 这里一行相当于上面的1-3步骤所做的事情
    //TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    //TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);
/*    TIM_TimeBaseInit(TIM2,&(TIM_TimeBaseInitTypeDef){
        // 配置预分频
        .TIM_ClockDivision = TIM_CKD_DIV1,
        // 把 72MHz 的频率分为 72MHz/10000 = 7200Hz
        .TIM_Prescaler = 10000-1,
        // 配置自动重装寄存器
        // 当计数达到 7200 时，触发后续中断
        .TIM_Period = 7200-1,
        
        // 从 0 往上数，直到特定数字
        .TIM_CounterMode = TIM_CounterMode_Up,
        .TIM_RepetitionCounter = 0x0000,
    });
*/    


    
    TIM_OC1Init(TIM4, &(TIM_OCInitTypeDef){
        .TIM_OCMode=TIM_OCMode_PWM1,
        // 设置输出使能
        .TIM_OutputState=TIM_OutputState_Enable,
        .TIM_Pulse=1250, // 设置捕获比较寄存器CCR的值，相应的能配置占空比
        .TIM_OCPolarity=TIM_OCPolarity_High, // 配置极性
    });
    
    // 当计数器抵达 50 的时候会触发一次
    // 又因为计数器到 100 的时候会被自动重装为 0
    // 所以这样配置能输出一个 占空比为 50% 的pwm 波形
    // TIM_OC1Init 的 TIM_Pulse 已经配置过了
    // TIM_SetCompare1(TIM2,50);
    
    // 开启 定时器2 通道一的输出
    //TIM_CCxCmd(TIM2,TIM_Channel_1,TIM_CCx_Enable);
    
    
    
    // 启动定时器
    TIM_Cmd(TIM4,ENABLE);
}

/**
    设置输出比较寄存器的值
*/
uint16_t set_speed(float output_rps,float max_rps){

    if(output_rps>0){
        clockwise_rotate();
    }else{
        counter_clockwise_rotate();
    }
    
    output_rps = fabs(output_rps);
    
    if (output_rps>100){
        output_rps = 100;
    }
        
    uint16_t output_duty = output_rps * 100 /  max_rps;

       
    TIM_SetCompare1(TIM2,output_duty);
    
    return output_duty;
}


